home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung CD 2 (Tewi)(1994).iso / c / compiler / cpp / cpp5.c < prev    next >
C/C++ Source or Header  |  1985-11-27  |  32KB  |  1,034 lines

  1.  
  2. /*
  3.  *                          C P P 5 . C
  4.  *              E x p r e s s i o n   E v a l u a t i o n
  5.  *
  6.  * Edit History
  7.  * 31-Aug-84    MM      USENET net.sources release
  8.  * 04-Oct-84    MM      __LINE__ and __FILE__ must call ungetstring()
  9.  *                      so they work correctly with token concatenation.
  10.  *                      Added string formal recognition.
  11.  * 25-Oct-84    MM      "Short-circuit" evaluate #if's so that we
  12.  *                      don't print unnecessary error messages for
  13.  *                      #if !defined(FOO) && FOO != 0 && 10 / FOO ...
  14.  * 31-Oct-84    ado/MM  Added token concatenation
  15.  *  6-Nov-84    MM      Split from #define stuff, added sizeof stuff
  16.  * 19-Nov-84    ado     #if error returns TRUE for (sigh) compatibility
  17.  * 22-Apr-85    ado/MM  added evalone to properly handle \value
  18.  * 29-Apr-85    ado     Cleaned up #if ... sizeof
  19.  */
  20.  
  21. #include        <stdio.h>
  22. #include        <ctype.h>
  23. #include        "cppdef.h"
  24. #include        "cpp.h"
  25.  
  26. /*
  27.  * Evaluate an #if expression.
  28.  */
  29.  
  30. static char     *opname[] = {           /* For debug and error messages */
  31. "end of expression", "val", "id",
  32.   "+",   "-",  "*",  "/",  "%",
  33.   "<<", ">>",  "&",  "|",  "^",
  34.   "==", "!=",  "<", "<=", ">=",  ">",
  35.   "&&", "||",  "?",  ":",  ",",
  36.   "unary +", "unary -", "~", "!",  "(",  ")", "(none)",
  37. };
  38.  
  39. /*
  40.  * opdope[] has the operator precedence:
  41.  *     Bits
  42.  *        7     Unused (so the value is always positive)
  43.  *      6-2     Precedence (000x .. 017x)
  44.  *      1-0     Binary op. flags:
  45.  *          01  The binop flag should be set/cleared when this op is seen.
  46.  *          10  The new value of the binop flag.
  47.  * Note:  Expected, New binop
  48.  * constant     0       1       Binop, end, or ) should follow constants
  49.  * End of line  1       0       End may not be preceeded by an operator
  50.  * binary       1       0       Binary op follows a value, value follows.
  51.  * unary        0       0       Unary op doesn't follow a value, value follows
  52.  *   (          0       0       Doesn't follow value, value or unop follows
  53.  *   )          1       1       Follows value.  Op follows.
  54.  */
  55.  
  56. static char     opdope[OP_MAX] = {
  57.   0001,                                 /* End of expression            */
  58.   0002,                                 /* Digit                        */
  59.   0000,                                 /* Letter (identifier)          */
  60.   0141, 0141, 0151, 0151, 0151,         /* ADD, SUB, MUL, DIV, MOD      */
  61.   0131, 0131, 0101, 0071, 0071,         /* ASL, ASR, AND,  OR, XOR      */
  62.   0111, 0111, 0121, 0121, 0121, 0121,   /*  EQ,  NE,  LT,  LE,  GE,  GT */
  63.   0061, 0051, 0041, 0041, 0031,         /* ANA, ORO, QUE, COL, CMA      */
  64. /*
  65.  * Unary op's follow
  66.  */
  67.   0160, 0160, 0160, 0160,               /* NEG, PLU, COM, NOT           */
  68.   0170, 0013, 0023,                     /* LPA, RPA, END                */
  69. };
  70. /*
  71.  * OP_QUE and OP_RPA have alternate precedences:
  72.  */
  73. #define OP_RPA_PREC     0013
  74. #define OP_QUE_PREC     0034
  75.  
  76. /*
  77.  * S_ANDOR and S_QUEST signal "short-circuit" boolean evaluation, so that
  78.  *      #if FOO != 0 && 10 / FOO ...
  79.  * doesn't generate an error message.  They are stored in optab.skip.
  80.  */
  81. #define S_ANDOR         2
  82. #define S_QUEST         1
  83.  
  84. typedef struct optab {
  85.     char        op;                     /* Operator                     */
  86.     char        prec;                   /* Its precedence               */
  87.     char        skip;                   /* Short-circuit: TRUE to skip  */
  88. } OPTAB;
  89. static int      evalue;                 /* Current value from evallex() */
  90.  
  91. #ifdef  nomacargs
  92. FILE_LOCAL int
  93. isbinary(op)
  94. register int    op;
  95. {
  96.         return (op >= FIRST_BINOP && op <= LAST_BINOP);
  97. }
  98.  
  99. FILE_LOCAL int
  100. isunary(op)
  101. register int    op;
  102. {
  103.         return (op >= FIRST_UNOP && op <= LAST_UNOP);
  104. }
  105. #else
  106. #define isbinary(op)    (op >= FIRST_BINOP && op <= LAST_BINOP)
  107. #define isunary(op)     (op >= FIRST_UNOP  && op <= LAST_UNOP)
  108. #endif
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126. /*
  127.  * The following definitions are used to specify basic variable sizes.
  128.  */
  129.  
  130. #ifndef S_CHAR
  131. #define S_CHAR          (sizeof (char))
  132. #endif
  133. #ifndef S_SINT
  134. #define S_SINT          (sizeof (short int))
  135. #endif
  136. #ifndef S_INT
  137. #define S_INT           (sizeof (int))
  138. #endif
  139. #ifndef S_LINT
  140. #define S_LINT          (sizeof (long int))
  141. #endif
  142. #ifndef S_FLOAT
  143. #define S_FLOAT         (sizeof (float))
  144. #endif
  145. #ifndef S_DOUBLE
  146. #define S_DOUBLE        (sizeof (double))
  147. #endif
  148. #ifndef S_PCHAR
  149. #define S_PCHAR         (sizeof (char *))
  150. #endif
  151. #ifndef S_PSINT
  152. #define S_PSINT         (sizeof (short int *))
  153. #endif
  154. #ifndef S_PINT
  155. #define S_PINT          (sizeof (int *))
  156. #endif
  157. #ifndef S_PLINT
  158. #define S_PLINT         (sizeof (long int *))
  159. #endif
  160. #ifndef S_PFLOAT
  161. #define S_PFLOAT        (sizeof (float *))
  162. #endif
  163. #ifndef S_PDOUBLE
  164. #define S_PDOUBLE       (sizeof (double *))
  165. #endif
  166. #ifndef S_PFPTR
  167. #define S_PFPTR         (sizeof (int (*)()))
  168. #endif
  169.  
  170.  
  171.  
  172.  
  173.  
  174. typedef struct types {
  175.     short       type;                   /* This is the bit if           */
  176.     char        *name;                  /* this is the token word       */
  177.     short       excluded;               /* but these aren't legal here  */
  178. } TYPES;
  179.  
  180. #define ANYSIGN         (T_SIGNED | T_UNSIGNED)
  181. #define ANYFLOAT        (T_FLOAT  | T_DOUBLE)
  182. #define ANYINT          (T_CHAR   | T_SHORT | T_INT | T_LONG)
  183.  
  184. static TYPES basic_types[] = {
  185.         T_CHAR,         "char",         ANYFLOAT | ANYINT,
  186.         T_INT,          "int",          ANYFLOAT | T_CHAR | T_INT,
  187.         T_FLOAT,        "float",        ANYFLOAT | ANYINT | ANYSIGN,
  188.         T_DOUBLE,       "double",       ANYFLOAT | ANYINT | ANYSIGN,
  189.         T_SHORT,        "short",        ANYFLOAT | ANYINT,
  190.         T_LONG,         "long",         ANYFLOAT | ANYINT,
  191.         T_SIGNED,       "signed",       ANYFLOAT | ANYINT | T_CHAR | T_INT,
  192.         T_UNSIGNED,     "unsigned",     ANYFLOAT | ANYINT | T_CHAR | T_INT,
  193.         0,              NULL,           0       /* Signal end           */
  194. };
  195.  
  196.  
  197. /*
  198.  * The order of this table is important -- it is also referenced by
  199.  * the command line processor to allow run-time overriding of the
  200.  * built-in size values.  The order must not be changed:
  201.  *      char, short, int, long, float, double (func pointer)
  202.  */
  203. SIZES size_table[] = {
  204.     { T_CHAR,   S_CHAR,         S_PCHAR         },      /* char         */
  205.     { T_SHORT,  S_SINT,         S_PSINT         },      /* short int    */
  206.     { T_INT,    S_INT,          S_PINT          },      /* int          */
  207.     { T_LONG,   S_LINT,         S_PLINT         },      /* long         */
  208.     { T_FLOAT,  S_FLOAT,        S_PFLOAT        },      /* float        */
  209.     { T_DOUBLE, S_DOUBLE,       S_PDOUBLE       },      /* double       */
  210.     { T_FPTR,   0,              S_PFPTR         },      /* int (*())    */
  211.     { 0,        0,              0               },      /* End of table */
  212. };
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222. int
  223. eval()
  224. /*
  225.  * Evaluate an expression.  Straight-forward operator precedence.
  226.  * This is called from control() on encountering an #if statement.
  227.  * It calls the following routines:
  228.  * evallex      Lexical analyser -- returns the type and value of
  229.  *              the next input token.
  230.  * evaleval     Evaluate the current operator, given the values on
  231.  *              the value stack.  Returns a pointer to the (new)
  232.  *              value stack.
  233.  * For compatiblity with older cpp's, this return returns 1 (TRUE)
  234.  * if a syntax error is detected.
  235.  */
  236. {
  237.         register int    op;             /* Current operator             */
  238.         register int    *valp;          /* -> value vector              */
  239.         register OPTAB  *opp;           /* Operator stack               */
  240.         int             prec;           /* Op precedence                */
  241.         int             binop;          /* Set if binary op. needed     */
  242.         int             op1;            /* Operand from stack           */
  243.         int             skip;           /* For short-circuit testing    */
  244.         int             value[NEXP];    /* Value stack                  */
  245.         OPTAB           opstack[NEXP];  /* Operand stack                */
  246.         extern int      *evaleval();    /* Does actual evaluation       */
  247.  
  248.         valp = value;
  249.         opp = opstack;
  250.         opp->op = OP_END;               /* Mark bottom of stack         */
  251.         opp->prec = opdope[OP_END];     /* And its precedence           */
  252.         opp->skip = 0;                  /* Not skipping now             */
  253.         binop = 0;
  254. again:  ;
  255. #ifdef  DEBUG_EVAL
  256.         printf("In #if at again: skip = %d, binop = %d, line is: %s",
  257.             opp->skip, binop, infile->bptr);
  258. #endif
  259.         if ((op = evallex(opp->skip)) == OP_SUB && binop == 0)
  260.             op = OP_NEG;                        /* Unary minus          */
  261.         else if (op == OP_ADD && binop == 0)
  262.             op = OP_PLU;                        /* Unary plus           */
  263.         else if (op == OP_FAIL)
  264.             return (1);                         /* Error in evallex     */
  265. #ifdef  DEBUG_EVAL
  266.         printf("op = %s, opdope = %03o, binop = %d, skip = %d\n",
  267.             opname[op], opdope[op], binop, opp->skip);
  268. #endif
  269.         if (op == DIG) {                        /* Value?               */
  270.             if (binop != 0) {
  271.                 cerror("misplaced constant in #if", NULLST);
  272.                 return (1);
  273.             }
  274.             else if (valp >= &value[NEXP-1]) {
  275.                 cerror("#if value stack overflow", NULLST);
  276.                 return (1);
  277.             }
  278.             else {
  279. #ifdef  DEBUG_EVAL
  280.                 printf("pushing %d onto value stack[%d]\n",
  281.                     evalue, valp - value);
  282. #endif
  283.                 *valp++ = evalue;
  284.                 binop = 1;
  285.             }
  286.             goto again;
  287.         }
  288.         else if (op > OP_END) {
  289.             cerror("Illegal #if line", NULLST);
  290.             return (1);
  291.         }
  292.         prec = opdope[op];
  293.         if (binop != (prec & 1)) {
  294.             cerror("Operator %s in incorrect context", opname[op]);
  295.             return (1);
  296.         }
  297.         binop = (prec & 2) >> 1;
  298.         for (;;) {
  299. #ifdef  DEBUG_EVAL
  300.             printf("op %s, prec %d., stacked op %s, prec %d, skip %d\n",
  301.                 opname[op], prec, opname[opp->op], opp->prec, opp->skip);
  302. #endif
  303.             if (prec > opp->prec) {
  304.                 if (op == OP_LPA)
  305.                     prec = OP_RPA_PREC;
  306.                 else if (op == OP_QUE)
  307.                     prec = OP_QUE_PREC;
  308.                 op1 = opp->skip;                /* Save skip for test   */
  309.                 /*
  310.                  * Push operator onto op. stack.
  311.                  */
  312.                 opp++;
  313.                 if (opp >= &opstack[NEXP]) {
  314.                     cerror("expression stack overflow at op \"%s\"",
  315.                         opname[op]);
  316.                     return (1);
  317.                 }
  318.                 opp->op = op;
  319.                 opp->prec = prec;
  320.                 skip = (valp[-1] != 0);         /* Short-circuit tester */
  321.                 /*
  322.                  * Do the short-circuit stuff here.  Short-circuiting
  323.                  * stops automagically when operators are evaluated.
  324.                  */
  325.                 if ((op == OP_ANA && !skip)
  326.                  || (op == OP_ORO && skip))
  327.                     opp->skip = S_ANDOR;        /* And/or skip starts   */
  328.                 else if (op == OP_QUE)          /* Start of ?: operator */
  329.                     opp->skip = (op1 & S_ANDOR) | ((!skip) ? S_QUEST : 0);
  330.                 else if (op == OP_COL) {        /* : inverts S_QUEST    */
  331.                     opp->skip = (op1 & S_ANDOR)
  332.                               | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST);
  333.                 }
  334.                 else {                          /* Other ops leave      */
  335.                     opp->skip = op1;            /*  skipping unchanged. */
  336.                 }
  337. #ifdef  DEBUG_EVAL
  338.                 printf("stacking %s, valp[-1] == %d at %s",
  339.                     opname[op], valp[-1], infile->bptr);
  340.                 dumpstack(opstack, opp, value, valp);
  341. #endif
  342.                 goto again;
  343.             }
  344.             /*
  345.              * Pop operator from op. stack and evaluate it.
  346.              * End of stack and '(' are specials.
  347.              */
  348.             skip = opp->skip;                   /* Remember skip value  */
  349.             switch ((op1 = opp->op)) {          /* Look at stacked op   */
  350.             case OP_END:                        /* Stack end marker     */
  351.                 if (op == OP_EOE)
  352.                     return (valp[-1]);          /* Finished ok.         */
  353.                 goto again;                     /* Read another op.     */
  354.  
  355.             case OP_LPA:                        /* ( on stack           */
  356.                 if (op != OP_RPA) {             /* Matches ) on input   */
  357.                     cerror("unbalanced paren's, op is \"%s\"", opname[op]);
  358.                     return (1);
  359.                 }
  360.                 opp--;                          /* Unstack it           */
  361.                 /* goto again;                  -- Fall through         */
  362.  
  363.             case OP_QUE:
  364.                 goto again;                     /* Evaluate true expr.  */
  365.  
  366.             case OP_COL:                        /* : on stack.          */
  367.                 opp--;                          /* Unstack :            */
  368.                 if (opp->op != OP_QUE) {        /* Matches ? on stack?  */
  369.                     cerror("Misplaced '?' or ':', previous operator is %s",
  370.                         opname[opp->op]);
  371.                     return (1);
  372.                 }
  373.                 /*
  374.                  * Evaluate op1.
  375.                  */
  376.             default:                            /* Others:              */
  377.                 opp--;                          /* Unstack the operator */
  378. #ifdef  DEBUG_EVAL
  379.                 printf("Stack before evaluation of %s\n", opname[op1]);
  380.                 dumpstack(opstack, opp, value, valp);
  381. #endif
  382.                 valp = evaleval(valp, op1, skip);
  383. #ifdef  DEBUG_EVAL
  384.                 printf("Stack after evaluation\n");
  385.                 dumpstack(opstack, opp, value, valp);
  386. #endif
  387.             }                                   /* op1 switch end       */
  388.         }                                       /* Stack unwind loop    */
  389. }
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414. FILE_LOCAL int
  415. evallex(skip)
  416. int             skip;           /* TRUE if short-circuit evaluation     */
  417. /*
  418.  * Return next eval operator or value.  Called from eval().  It
  419.  * calls a special-purpose routines for 'char' strings and
  420.  * numeric values:
  421.  * evalchar     called to evaluate 'x'
  422.  * evalnum      called to evaluate numbers.
  423.  */
  424. {
  425.         register int    c, c1, t;
  426.  
  427. again:  do {                                    /* Collect the token    */
  428.             c = skipws();
  429.             if ((c = macroid(c)) == EOF_CHAR || c == '\n') {
  430.                 unget();
  431.                 return (OP_EOE);                /* End of expression    */
  432.             }
  433.         } while ((t = type[c]) == LET && catenate());
  434.         if (t == INV) {                         /* Total nonsense       */
  435.             if (!skip) {
  436.                 if (isascii(c) && isprint(c))
  437.                     cierror("illegal character '%c' in #if", c);
  438.                 else
  439.                     cierror("illegal character (%d decimal) in #if", c);
  440.             }
  441.             return (OP_FAIL);
  442.         }
  443.         else if (t == QUO) {                    /* ' or "               */
  444.             if (c == '\'') {                    /* Character constant   */
  445.                 evalue = evalchar(skip);        /* Somewhat messy       */
  446. #ifdef  DEBUG_EVAL
  447.                 printf("evalchar returns %d.\n", evalue);
  448. #endif
  449.                 return (DIG);                   /* Return a value       */
  450.             }
  451.             cerror("Can't use a string in an #if", NULLST);
  452.             return (OP_FAIL);
  453.         }
  454.         else if (t == LET) {                    /* ID must be a macro   */
  455.             if (streq(token, "defined")) {      /* Or defined name      */
  456.                 c1 = c = skipws();
  457.                 if (c == '(')                   /* Allow defined(name)  */
  458.                     c = skipws();
  459.                 if (type[c] == LET) {
  460.                     evalue = (lookid(c) != NULL);
  461.                     if (c1 != '('               /* Need to balance      */
  462.                      || skipws() == ')')        /* Did we balance?      */
  463.                         return (DIG);           /* Parsed ok            */
  464.                 }
  465.                 cerror("Bad #if ... defined() syntax", NULLST);
  466.                 return (OP_FAIL);
  467.             }
  468.             else if (streq(token, "sizeof"))    /* New sizeof hackery   */
  469.                 return (dosizeof());            /* Gets own routine     */
  470.             /*
  471.              * The Draft ANSI C Standard says that an undefined symbol
  472.              * in an #if has the value zero.  We are a bit pickier,
  473.              * warning except where the programmer was careful to write
  474.              *          #if defined(foo) ? foo : 0
  475.              */
  476.             if (!skip)
  477.                 cwarn("undefined symbol \"%s\" in #if, 0 used", token);
  478.             evalue = 0;
  479.             return (DIG);
  480.         }
  481.         else if (t == DIG) {                    /* Numbers are harder   */
  482.             evalue = evalnum(c);
  483. #ifdef  DEBUG_EVAL
  484.             printf("evalnum returns %d.\n", evalue);
  485. #endif
  486.         }
  487.         else if (strchr("!=<>&|\\", c) != NULL) {
  488.             /*
  489.              * Process a possible multi-byte lexeme.
  490.              */
  491.             c1 = cget();                        /* Peek at next char    */
  492.             switch (c) {
  493.             case '!':
  494.                 if (c1 == '=')
  495.                     return (OP_NE);
  496.                 break;
  497.  
  498.             case '=':
  499.                 if (c1 != '=') {                /* Can't say a=b in #if */
  500.                     unget();
  501.                     cerror("= not allowed in #if", NULLST);
  502.                     return (OP_FAIL);
  503.                 }
  504.                 return (OP_EQ);
  505.  
  506.             case '>':
  507.             case '<':
  508.                 if (c1 == c)
  509.                     return ((c == '<') ? OP_ASL : OP_ASR);
  510.                 else if (c1 == '=')
  511.                     return ((c == '<') ? OP_LE  : OP_GE);
  512.                 break;
  513.  
  514.             case '|':
  515.             case '&':
  516.                 if (c1 == c)
  517.                     return ((c == '|') ? OP_ORO : OP_ANA);
  518.                 break;
  519.  
  520.             case '\\':
  521.                 if (c1 == '\n')                 /* Multi-line if        */
  522.                     goto again;
  523.                 cerror("Unexpected \\ in #if", NULLST);
  524.                 return (OP_FAIL);
  525.             }
  526.             unget();
  527.         }
  528.         return (t);
  529. }
  530.  
  531.  
  532.  
  533.  
  534. FILE_LOCAL int
  535. dosizeof()
  536. /*
  537.  * Process the sizeof (basic type) operation in an #if string.
  538.  * Sets evalue to the size and returns
  539.  *      DIG             success
  540.  *      OP_FAIL         bad parse or something.
  541.  */
  542. {
  543.         register int    c;
  544.         register TYPES  *tp;
  545.         register SIZES  *sizp;
  546.         short           typecode;
  547.  
  548.         if ((c = skipws()) != '(')
  549.             goto nogood;
  550.         /*
  551.          * Scan off the tokens.
  552.          */
  553.         typecode = 0;
  554.         while ((c = skipws())) {
  555.             if ((c = macroid(c)) == EOF_CHAR || c == '\n')
  556.                 goto nogood;                    /* End of line is a bug */
  557.             else if (c == '(') {                /* thing (*)() func ptr */
  558.                 if (skipws() == '*'
  559.                  && skipws() == ')') {          /* We found (*)         */
  560.                     if (skipws() != '(')        /* Let () be optional   */
  561.                         unget();
  562.                     else if (skipws() != ')')
  563.                         goto nogood;
  564.                     typecode |= T_FPTR;         /* Function pointer     */
  565.                 }
  566.                 else {                          /* Junk is a bug        */
  567.                     goto nogood;
  568.                 }
  569.             }
  570.             else if (type[c] != LET)            /* Exit if not a type   */
  571.                 break;
  572.             else if (!catenate()) {             /* Maybe combine tokens */
  573.                 /*
  574.                  * Look for this unexpandable token in basic_types.
  575.                  */
  576.                 for (tp = basic_types; tp->name != NULLST; tp++) {
  577.                     if (streq(token, tp->name))
  578.                         break;
  579.                 }
  580.                 if (tp->name == NULLST) {
  581.                     cerror("#if sizeof, unknown type \"%s\"", token);
  582.                     return (OP_FAIL);
  583.                 }
  584.                 if ((typecode & tp->excluded) != 0) {
  585.                     cerror("#if sizeof: illegal type combination", NULLST);
  586.                     return (OP_FAIL);
  587.                 }
  588.                 typecode |= tp->type;           /* Or in the type bit   */
  589.             }
  590.         }
  591.         /*
  592.          * We are at the end of the type scan.  Chew off '*' if necessary.
  593.          */
  594.         if (c == '*') {
  595.             typecode |= T_PTR;
  596.             c = skipws();
  597.         }
  598.         if (c == ')') {                         /* Last syntax check    */
  599.             /*
  600.              * We assume that all function pointers are the same size:
  601.              *          sizeof (int (*)()) == sizeof (float (*)())
  602.              * We assume that signed and unsigned don't change the size:
  603.              *          sizeof (signed int) == (sizeof unsigned int)
  604.              */
  605.             if ((typecode & T_FPTR) != 0)       /* Function pointer     */
  606.                 typecode = T_FPTR | T_PTR;
  607.             else {                              /* Var or var * datum   */
  608.                 typecode &= ~(T_SIGNED | T_UNSIGNED);
  609.                 if ((typecode & (T_SHORT | T_LONG)) != 0)
  610.                     typecode &= ~T_INT;
  611.             }
  612.             if ((typecode & ~T_PTR) == 0) {
  613.                 cerror("#if sizeof() error, no type specified", NULLST);
  614.                 return (OP_FAIL);
  615.             }
  616.             /*
  617.              * Exactly one bit (and possibly T_PTR) may be set.
  618.              */
  619.             for (sizp = size_table; sizp->bits != 0; sizp++) {
  620.                 if ((typecode & ~T_PTR) == sizp->bits) {
  621.                     evalue = ((typecode & T_PTR) != 0)
  622.                         ? sizp->psize : sizp->size;
  623.                     return (DIG);
  624.                 }
  625.             }                                   /* We shouldn't fail    */
  626.             cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode);
  627.             return (OP_FAIL);
  628.         }
  629.  
  630. nogood: unget();
  631.         cerror("#if ... sizeof() syntax error", NULLST);
  632.         return (OP_FAIL);
  633. }
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654. FILE_LOCAL int
  655. evalnum(c)
  656. register int    c;
  657. /*
  658.  * Expand number for #if lexical analysis.  Note: evalnum recognizes
  659.  * the unsigned suffix, but only returns a signed int value.
  660.  */
  661. {
  662.         register int    value;
  663.         register int    base;
  664.         register int    c1;
  665.  
  666.         if (c != '0')
  667.             base = 10;
  668.         else if ((c = cget()) == 'x' || c == 'X') {
  669.                 base = 16;
  670.                 c = cget();
  671.         }
  672.         else base = 8;
  673.         value = 0;
  674.         for (;;) {
  675.             c1 = c;
  676.             if (isascii(c) && isupper(c1))
  677.                 c1 = tolower(c1);
  678.             if (c1 >= 'a')
  679.                 c1 -= ('a' - 10);
  680.             else c1 -= '0';
  681.             if (c1 < 0 || c1 >= base)
  682.                 break;
  683.             value *= base;
  684.             value += c1;
  685.             c = cget();
  686.         }
  687.         if (c == 'u' || c == 'U')       /* Unsigned nonsense            */
  688.             c = cget();
  689.         unget();
  690.         return (value);
  691. }
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702. FILE_LOCAL int
  703. evalchar(skip)
  704. int             skip;           /* TRUE if short-circuit evaluation     */
  705. /*
  706.  * Get a character constant
  707.  */
  708. {
  709.         register int    c;
  710.         register int    value;
  711. #if BIG_ENDIAN
  712.         register int    count;
  713. #endif
  714.  
  715.         instring = TRUE;
  716.         if ((value = evalone()) == EOF_CHAR) {
  717.             switch (cget()) {
  718.             case '\'':                  /* Empty char constant          */
  719.                 cerror("Empty character constant", NULLST);
  720.                 return (0);
  721.  
  722.             /* case '\n':               -- Unterminated char constant   */
  723.             default:                    /* Junk or eof                  */
  724.                 cerror("Unterminated character constant", NULLST);
  725.                 return (0);
  726.             }
  727.         }
  728.         /*
  729.          * We warn on multi-byte constants and try to hack
  730.          * (big|little)endian machines.
  731.          */
  732. #if BIG_ENDIAN
  733.         count = 0;
  734. #endif
  735.         while ((c = evalone()) != EOF_CHAR) {
  736.             if (!skip)
  737.                 ciwarn("multi-byte constant '%c' isn't portable", c);
  738. #if BIG_ENDIAN
  739.             count += BITS_CHAR;
  740.             value += (c << count);
  741. #else
  742.             value <<= BITS_CHAR;
  743.             value += c;
  744. #endif
  745.         }
  746.         switch (cget()) {
  747.         case '\'':                      /* Normal char termination      */
  748.             break;
  749.  
  750.         /* case '\n':                   -- End of line seen             */
  751.         default:                        /* Junk or end of file seen     */
  752.             cerror("Unterminated multi-character constant", NULLST);
  753.             break;
  754.         }
  755.         instring = FALSE;
  756.         return (value);
  757. }
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774. FILE_LOCAL int
  775. evalone()
  776. /*
  777.  * Called from evalchar() above to get a single character with \ escapes.
  778.  * Returns the character or EOF_CHAR (on errors).
  779.  */
  780. {
  781.         register char   *cp;
  782.         register char   *digits;
  783.         register int    c;
  784.         register int    value;
  785.         register int    count;
  786.         extern char     *strchr();
  787.  
  788.         switch (c = cget()) {
  789.         default:
  790.             return (c);
  791.  
  792.         case '\n':
  793.         case '\'':
  794.             unget();
  795.             return (EOF_CHAR);                  /* Exits mult-char loop */
  796.  
  797.         case '\\':                              /* \ escape seen        */
  798.             break;
  799.         }
  800.         switch (c = cget()) {
  801.         case 'a':                               /* New in Standard      */
  802. #if ('a' == '\a' || '\a' == ALERT)
  803.             return (ALERT);                     /* Use predefined value */
  804. #else
  805.             return ('\a');                      /* Use compiler's value */
  806. #endif
  807.  
  808.         case 'b':
  809.             return ('\b');
  810.  
  811.         case 'f':
  812.             return ('\f');
  813.  
  814.         case 'n':
  815.             return ('\n');
  816.  
  817.         case 'r':
  818.             return ('\r');
  819.  
  820.         case 't':
  821.             return ('\t');
  822.  
  823.         case 'v':                               /* New in Standard      */
  824. #if ('v' == '\v' || '\v' == VT)
  825.             return (VT);                        /* Use predefined value */
  826. #else
  827.             return ('\v');                      /* Use compiler's value */
  828. #endif
  829.  
  830.         case 'x':                               /* '\xFF'               */
  831.             digits = "0123456789abcdef";
  832.             c = cget();
  833.             break;
  834.  
  835.         case '0': case '1': case '2': case '3':
  836.         case '4': case '5': case '6': case '7':
  837.             digits = "01234567";
  838.             break;
  839.  
  840.         default:
  841.             return (c);
  842.         }
  843.         value = 0;
  844.         for (count = 0; count < 3; ++count) {
  845.             if (c == EOF_CHAR)
  846.                 return (c);
  847.             if (isascii(c) && isupper(c))
  848.                 c = tolower(c);
  849.             if ((cp = strchr(digits, c)) == 0)
  850.                 break;
  851.             value = value * strlen(digits) + cp - digits;
  852.             c = cget();
  853.         }
  854.         unget();
  855.         if (count == 0)                         /* '\xnonsense'         */
  856.             return (EOF_CHAR);
  857.         return (value);
  858. }
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870. FILE_LOCAL int *
  871. evaleval(valp, op, skip)
  872. register int    *valp;
  873. int             op;
  874. int             skip;           /* TRUE if short-circuit evaluation     */
  875. /*
  876.  * Apply the argument operator to the data on the value stack.
  877.  * One or two values are popped from the value stack and the result
  878.  * is pushed onto the value stack.
  879.  *
  880.  * OP_COL is a special case.
  881.  *
  882.  * evaleval() returns the new pointer to the top of the value stack.
  883.  */
  884. {
  885.         register int    v1, v2;
  886.  
  887.         if (isbinary(op))
  888.             v2 = *--valp;
  889.         v1 = *--valp;
  890. #ifdef  DEBUG_EVAL
  891.         printf("%s op %s", (isbinary(op)) ? "binary" : "unary",
  892.             opname[op]);
  893.         if (isbinary(op))
  894.             printf(", v2 = %d.", v2);
  895.         printf(", v1 = %d.\n", v1);
  896. #endif
  897.         switch (op) {
  898.         case OP_EOE:
  899.              break;
  900.  
  901.         case OP_ADD:
  902.             v1 += v2;
  903.             break;
  904.  
  905.         case OP_SUB:
  906.             v1 -= v2;
  907.             break;
  908.  
  909.         case OP_MUL:
  910.             v1 *= v2;
  911.             break;
  912.  
  913.         case OP_DIV:
  914.         case OP_MOD:
  915.             if (v2 == 0) {
  916.                 if (!skip) {
  917.                     cwarn("%s by zero in #if, zero result assumed",
  918.                         (op == OP_DIV) ? "divide" : "mod");
  919.                 }
  920.                 v1 = 0;
  921.             }
  922.             else if (op == OP_DIV)
  923.                 v1 /= v2;
  924.             else
  925.                 v1 %= v2;
  926.             break;
  927.  
  928.         case OP_ASL:
  929.             v1 <<= v2;
  930.             break;
  931.  
  932.         case OP_ASR:
  933.             v1 >>= v2;
  934.             break;
  935.  
  936.         case OP_AND:
  937.             v1 &= v2;
  938.             break;
  939.  
  940.         case OP_OR:
  941.             v1 |= v2;
  942.             break;
  943.  
  944.         case OP_XOR:
  945.             v1 ^= v2;
  946.             break;
  947.  
  948.         case OP_EQ:
  949.             v1 = (v1 == v2);
  950.             break;
  951.  
  952.         case OP_NE:
  953.             v1 = (v1 != v2);
  954.             break;
  955.  
  956.         case OP_LT:
  957.             v1 = (v1 < v2);
  958.             break;
  959.  
  960.         case OP_LE:
  961.             v1 = (v1 <= v2);
  962.             break;
  963.  
  964.         case OP_GE:
  965.             v1 = (v1 >= v2);
  966.             break;
  967.  
  968.         case OP_GT:
  969.             v1 = (v1 > v2);
  970.             break;
  971.  
  972.         case OP_ANA:
  973.             v1 = (v1 && v2);
  974.             break;
  975.  
  976.         case OP_ORO:
  977.             v1 = (v1 || v2);
  978.             break;
  979.  
  980.         case OP_COL:
  981.             /*
  982.              * v1 has the "true" value, v2 the "false" value.
  983.              * The top of the value stack has the test.
  984.              */
  985.             v1 = (*--valp) ? v1 : v2;
  986.             break;
  987.  
  988.         case OP_NEG:
  989.             v1 = (-v1);
  990.             break;
  991.  
  992.         case OP_PLU:
  993.             break;
  994.  
  995.         case OP_COM:
  996.             v1 = ~v1;
  997.             break;
  998.  
  999.         case OP_NOT:
  1000.             v1 = !v1;
  1001.             break;
  1002.  
  1003.         default:
  1004.             cierror("#if bug, operand = %d.", op);
  1005.             v1 = 0;
  1006.         }
  1007.         *valp++ = v1;
  1008.         return (valp);
  1009. }
  1010.  
  1011.  
  1012.  
  1013.  
  1014. #ifdef  DEBUG_EVAL
  1015. dumpstack(opstack, opp, value, valp)
  1016. OPTAB           opstack[NEXP];  /* Operand stack                */
  1017. register OPTAB  *opp;           /* Operator stack               */
  1018. int             value[NEXP];    /* Value stack                  */
  1019. register int    *valp;          /* -> value vector              */
  1020. {
  1021.         printf("index op prec skip name -- op stack at %s", infile->bptr);
  1022.         while (opp > opstack) {
  1023.             printf(" [%2d] %2d  %03o    %d %s\n", opp - opstack,
  1024.                 opp->op, opp->prec, opp->skip, opname[opp->op]);
  1025.             opp--;
  1026.         }
  1027.         while (--valp >= value) {
  1028.             printf("value[%d] = %d\n", (valp - value), *valp);
  1029.         }
  1030. }
  1031. #endif
  1032.  
  1033.  
  1034.